<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  

  
  <title>dagger2整个流程解析（一） | 海晨忆的博客</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  
  
  
  <meta name="description" content="&amp;emsp;&amp;emsp;众所周知，dagger的入门是比较难的，在嵌入之前，我先说一下这个dagger必要的东西，也是比较常见的东西，几个注解 @Component，@Singleton，@Module，@Provides，@Inject">
<meta property="og:type" content="article">
<meta property="og:title" content="dagger2整个流程解析（一）">
<meta property="og:url" content="https://haichenyi.com/2019/07/31/dagger2整个流程解析（一）/index.html">
<meta property="og:site_name" content="海晨忆的博客">
<meta property="og:description" content="&amp;emsp;&amp;emsp;众所周知，dagger的入门是比较难的，在嵌入之前，我先说一下这个dagger必要的东西，也是比较常见的东西，几个注解 @Component，@Singleton，@Module，@Provides，@Inject">
<meta property="og:locale" content="zh-Hans">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图一.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图五.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图二.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图三.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图四.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图六.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图七.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图八.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图九.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图九.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图十一.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图十二.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图十三.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图十四.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图十五.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图十六.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图十七.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图十八.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图十九.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图二十.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图二十一.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图二十二.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图二十三.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图二十四.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图二十五.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图二十六.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图二十七.png">
<meta property="og:image" content="https://haichenyi.com/uploads/article/2019-07-31/图二十八.png">
<meta property="og:updated_time" content="2019-09-18T09:02:34.288Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="dagger2整个流程解析（一）">
<meta name="twitter:description" content="&amp;emsp;&amp;emsp;众所周知，dagger的入门是比较难的，在嵌入之前，我先说一下这个dagger必要的东西，也是比较常见的东西，几个注解 @Component，@Singleton，@Module，@Provides，@Inject">
<meta name="twitter:image" content="https://haichenyi.com/uploads/article/2019-07-31/图一.png">
  
    <link rel="alternate" href="/atom.xml" title="海晨忆的博客" type="application/atom+xml">
  
  
    <link rel="icon" href="/uploads/artistic_image/head.jpg">
  
  
    <link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
  
  <link rel="stylesheet" href="/css/style.css">
  <link rel="stylesheet" href="/css/highlight.css">
  <script>
  let antiquityStorage = window.sessionStorage.getItem('antiquitySessionStorage');
  if (antiquityStorage == '' || antiquityStorage == null) {
    var antiquityLoader = '<div id="loaderbox"><div class="loader"><div class="load-roll"><div class="load-top"></div><div class="load-right"></div><div class="load-bottom"></div></div></div></div>';
    document.write(antiquityLoader);
    document.body.style.overflow = 'hidden'
  }
  </script>
</head>

<body>
  <div id="fullpage" class="mobile-nav-right">
    
      <div id="wrapper" style="background-image: url(/uploads/artistic_image/bg.jpg)" title="背景图片来自网络">
    
    
      <header id="header">
  <div id="nav-toggle" class="nav-toggle"></div>
  <div class="head-box global-width">
    <nav class="nav-box nav-right">
      
        <a class="nav-item" href="/" title
        
        >首页</a>
      
        <a class="nav-item" href="/archives" title
        
        >归档</a>
      
        <a class="nav-item" href="/about" title
        
        >简历</a>
      
    </nav>
  </div>
</header>
      <div id="middlecontent" title class="global-width sidebar-left">
        <section id="main"><article id="post-dagger2整个流程解析（一）" class="article global-container article-type-post" itemscope itemprop="blogPost">
  
    <header class="article-header">
      
  
    <h1 class="article-title" itemprop="name">
      dagger2整个流程解析（一）
    </h1>
  

    </header>
  
  <div class="article-meta">
    <a href="/2019/07/31/dagger2整个流程解析（一）/" class="article-date">
  <time datetime="2019-07-31T12:17:33.000Z" itemprop="datePublished">2019-07-31</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/categories/Android-源码解析/">Android -源码解析</a>
  </div>

    
  </div>
  
    <span id="busuanzi_container_page_pv">
      本文总阅读量<span id="busuanzi_value_page_pv"></span>次
    </span>
  

  <div class="article-inner">
    
    <div class="article-content article-content-cloud doorframe mac" itemprop="articleBody">
      
        <p>&emsp;&emsp;众所周知，dagger的入门是比较难的，在嵌入之前，我先说一下这个dagger必要的东西，也是比较常见的东西，几个注解 <strong>@Component</strong>，<strong>@Singleton</strong>，<strong>@Module</strong>，<strong>@Provides</strong>，<strong>@Inject</strong></p>
<a id="more"></a>
<p>&emsp;&emsp;<strong>大致的整个流程如下：</strong></p>
<ol>
<li>编译的时候，先找构造方法由@Inject标记的类，生成对应的Factory.class类，这个类里面通过new生成对应的对象</li>
<li>然后，moudle里面，每一个由@Provider标记的方法，都会生成一个对应的Factory.class文件，这里返回的对象，就是刚才由new生成的对象</li>
<li>最后，我们通过component获取对象的时候，就找moudle去取。moudle取的对象就是之前new生成的</li>
</ol>
<p>&emsp;&emsp;<strong>也可以这样理解：</strong></p>
<ol>
<li>@Component直到桥梁的作用，告诉application,activity我能给你提供哪些对象</li>
<li>当Component中返回对象时，它会到@Module中去找这个对象创建没</li>
<li>@Module中的方法很多，它不可以每个方法的识别一次，它只找@Provider标记的方法</li>
</ol>
<p>&emsp;&emsp;<strong>后文的说明都是依赖于<a href="https://github.com/haichenyi/KotlinMvp" target="_blank" rel="noopener">kotlin框架</a></strong></p>
<p>&emsp;&emsp;这里我拿如下方法来说明整个流程：</p>
<p><img src="/uploads/article/2019-07-31/图一.png" alt="图一.png"></p>
<p>如上图：在AppComponent里面的getSpHelper()方法，返回对象就是SpHelper，前面我们说了，component里面需要的对象要在moudle里面找，moudle里面需要的对象要在@Inject的地方生成，所以，moudle里面也要有对应的方法：如下图：</p>
<p><img src="/uploads/article/2019-07-31/图五.png" alt="图五.png"></p>
<p>这里的，整个SpHelper是个什么东西呢？参数SpReal又是个什么东西呢？他就是一个sharePreference的接口。SpReal是SpHelper的实现类，如下图：</p>
<p><img src="/uploads/article/2019-07-31/图二.png" alt="图二.png"></p>
<p>这个就是一个普通的接口，与dagger2搭不上边。我们看他的实现类：</p>
<p><img src="/uploads/article/2019-07-31/图三.png" alt="图三.png"></p>
<p>如上图：类SpReal实现SpHelper接口，并且，它的构造方法用@Inject标记了。这里就跟我们的dagger2搭上关系了，我们就需要找SpReal对应的Factory.clss文件。如下图：</p>
<p><img src="/uploads/article/2019-07-31/图四.png" alt="图四.png"></p>
<p>如上图，SpReal_Factory类有三个方法，两个get()方法返回SpReal对象，静态的newInstance()方法也是返回SpReal对象，静态的create()方法，返回的是当前类的对象。那么，这里的调用顺序是什么呢？</p>
<p>我们在转过头来看看moudle里面方法对应的Factory：如下图</p>
<p><img src="/uploads/article/2019-07-31/图六.png" alt="图六.png"></p>
<p>如上图，左边我们看到AppMoudle生成了三个对应的Factory文件，为什么会生成三个？因为，我们的AppMoudle里面有三个方法是用注解@Provides标记的，可以回过头去看一下AppMoudle的内容。</p>
<p>我们仔细看一下，我们需要的这个类的内容AppModule_ProvideSpHelperFactory，一共有四个方法：一个构造方法，一个get方法，一个create方法，一个provideSpHelper方法。</p>
<p>是不是很眼熟这个providerSpHelper方法，并且他的返回值也是SpHelper，没错，这个方法就是我们AppMoudle里面定义的方法，在这里生成的对应的方法，它只是参数多了一个AppModule，为什么会多了这个参数呢？带着这个问题，我们看这个方法的实现：</p>
<p><img src="/uploads/article/2019-07-31/图七.png" alt="图七.png"></p>
<p>可以点击跳转这个方法，你会发现，它跳转回我们的AppMoudle方法里面对应的provideSpHelper()方法。回过头来想，我们的AppMoudle就是一个类，里面的provideSpHelper()就是一个普通的方法，怎么调用这个方法呢？就只有用 <strong>对象.方法名()</strong> 调用，所以，这里参数就多加了一个AppMoudle。</p>
<p>上面解释了为什么多了一个参数，我们再来看一下这个方法的实现。如下图：</p>
<p><img src="/uploads/article/2019-07-31/图八.png" alt="图八.png"></p>
<p>如上图，就是一个非空判断，如果为空就抛出空指针异常，如果不为空，就返回第一个参数。第一个参数是什么呢？第一个参数，不就是，我们上面说的对象调用方法名么？我们来看一下它这里是怎么实现的。如下图</p>
<p><img src="/uploads/article/2019-07-31/图九.png" alt="图九.png"></p>
<p>咦，怎么又返回来了？回到AppMoudle类了，它没有给我们实现啊？我们再想想，首先这个方法，返回的是第一个参数的值，第一个参数又是一个调用我们AppMoudle里面的方法，我们AppMoudle这个方法的返回值，就是这里这个方法的返回值。我们看一下，我们方法的返回值是什么？</p>
<p><img src="/uploads/article/2019-07-31/图九.png" alt="图十.png"></p>
<p>我们方法的返回值，不就是传进来的参数么？那我们再看看这里方法传进来的参数是什么？</p>
<p><img src="/uploads/article/2019-07-31/图十一.png" alt="图十一.png"></p>
<p>它这里的传的参数，就是这个方法的第二个参数。到这里，我们又断了，依然不知道，这个参数从哪来的。</p>
<p>冷静下来想一想，调用方法，参数从哪里来？我们从方法里面实现怎么看的到，我们肯定是要在调用方法的地方看。所以，我们就要找到在哪调用这个方法的。既然是写在AppComponent里面，那我们就找他的编译后生成的文件，也就是DaggerAppComponent，如下图：</p>
<p><img src="/uploads/article/2019-07-31/图十二.png" alt="图十二.png"></p>
<p>一眼看过去，这么多东西，怎么看？我又想到，这个DaggerAppComponent类是由AppComponent生成的类，通过上面的判断，这个类里面也应该有我在AppComponent定义的方法的实现才对，搜一下getSpHelper方法，果不其然。如下图：</p>
<p><img src="/uploads/article/2019-07-31/图十三.png" alt="图十三.png"></p>
<p>如上图，我们可以看到这个方法的实现，类点方法名，说明整个方法是静态的，我们点过去一看。如下图：</p>
<p><img src="/uploads/article/2019-07-31/图十四.png" alt="图十四.png"></p>
<p>不就是，我们前面说的那个静态方法吗？这样就跟我们前面分析的都串起来了。我们前面的问题是什么？不就是不知道这个方法的第二个参数从哪来的吗？现在，我们看到了，就是在这里new出来的。</p>
<p>至于第一个参数AppMoudle从哪来的？我们可以接着分析一下。如下图</p>
<p><img src="/uploads/article/2019-07-31/图十五.png" alt="图十五.png"></p>
<p>我们可以看到这个appMoudle定义的是一个全局的变量，我们就要找，在哪里初始化的？如下图：</p>
<p><img src="/uploads/article/2019-07-31/图十六.png" alt="图十六.png"></p>
<p>我们发现它是在构造方法里面初始化的，我们就要找在哪里调用的这个构造方法。如下图</p>
<p><img src="/uploads/article/2019-07-31/图十七.png" alt="图十七.png"></p>
<p>我们发现，在这个Builder类里面的build()方法调用的这个构造方法，我们就找在哪里调用的这个build()方法。如下图：</p>
<p><img src="/uploads/article/2019-07-31/图十八.png" alt="图十八.png"></p>
<p>我们发现，是AndroidInjector这个接口里面的抽象Builder类，这个抽象Builder类实现的是AndroidInjector.Factory，我们要找的就是这个create()方法。</p>
<p><img src="/uploads/article/2019-07-31/图十九.png" alt="图十九.png"></p>
<p>所以，这里在我们的Application里面初始化的，也就是我这里的MyApp里面初始化的。这个参数怎么传递的？如下图：</p>
<p><img src="/uploads/article/2019-07-31/图二十.png" alt="图二十.png"></p>
<p>在create方法里面调用build()之前还调用了seedInstance()方法，这里是抽象类的方法，要想知道这个方法是怎么实现的，那就得看他的实现类。这个Builder<t>的实现类是谁？想一想上面是怎么跳转过来的？不想这个，我们也可以点这个类进行跳转。如下图</t></p>
<p><img src="/uploads/article/2019-07-31/图二十一.png" alt="图二十一.png"></p>
<p>如上图，我们可以看到有两个地方调用，一个是ActComponent，一个是AppComponent，前面一个是activity相关的，我们还没有说到，我们现在一直说的都是Application相关的。所以，这里跳转的地方，肯定是Application。如下图</p>
<p><img src="/uploads/article/2019-07-31/图二十二.png" alt="图二十二.png"></p>
<p>这个方法还过时了，正好，我们这个Builder<t>抽象类还用@Deprecated标记了。诶？那这里还是没有实现啊，这也是一个抽象类。这个是抽象类，AppComponent又是一个接口，所以，我们要找这个AppComponent接口的实现类。如下图：</t></p>
<p><img src="/uploads/article/2019-07-31/图二十三.png" alt="图二十三.png"></p>
<p>如上图，AppComponent的实现类，就是DaggerAppComponent类。我们在这个类里面找Builder<t>的实现类就可以了。找找找，如下图</t></p>
<p><img src="/uploads/article/2019-07-31/图二十四.png" alt="图二十四.png"></p>
<p>如上图，这里有seedInstance方法和build两个方法，而且都是@Override的，从父类继承过来的，我们在看看AndroidInjector类。如下图：</p>
<p><img src="/uploads/article/2019-07-31/图二十五.png" alt="图二十五.png"></p>
<p>正好，它有这两个方法，并且还都是抽象方法。所以，这个类就是它的实现类。所以，调用的seedInstance方法，就是这里的这个方法。如下图：</p>
<p><img src="/uploads/article/2019-07-31/图二十六.png" alt="图二十六.png"></p>
<p>这个方法就是做了一个赋值操作，赋值之前做了一个非空检验。所以，在执行build()的时候这个seedInstance对象已经赋值了，不是空。所以这里就走通了。如下图</p>
<p><img src="/uploads/article/2019-07-31/图二十七.png" alt="图二十七.png"></p>
<p>如上的构造方法就走通了，那么appMoudle就有值了，那么我们前面的问题。如下图：</p>
<p><img src="/uploads/article/2019-07-31/图二十八.png" alt="图二十八.png"></p>
<p>我们之前就是在这里，不知道这个appMoudle是怎么赋值的，这里已经走通了。这就是通过AppComponent过去getSpHelper()的整个流程了</p>

      
    </div>
    
      <footer class="article-footer">
        完
      </footer>
    
  </div>
  
    
<nav id="article-nav">
  <div class="article-nav-block">
    
      <a href="/2019/08/22/SpringBoot系列—Hello-World（一）/" id="article-nav-newer" class="article-nav-link-wrap">
        <strong class="article-nav-caption"></strong>
        <div class="article-nav-title">
          
            SpringBoot系列—Hello World（一）
          
        </div>
      </a>
    
  </div>
  <div class="article-nav-block">
    
      <a href="/2019/07/31/一场由dagger2引发的一些思考/" id="article-nav-older" class="article-nav-link-wrap">
        <div class="article-nav-title">一场由dagger2引发的一些思考</div>
        <strong class="article-nav-caption"></strong>
      </a>
    
  </div>
</nav>

    
  
  
</article>
</section>
        <aside id="sidebar">
  
    <div class="widget-box">
  <div class="avatar-box avatar-item">
    <img class="avatar" src="/uploads/artistic_image/head.jpg" title="头像来自网络"></img>
    <h3 class="avatar-name">
      
        海晨忆
      
    </h3>
    <p class="avatar-slogan">
      先谋生，再谋爱。人间值得，未来可期。
    </p>
  </div>
</div>


  
    
  <div class="widget-box">
    <h3 class="widget-title">分类</h3>
    <div class="widget">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/categories/Android-Socket/">Android -Socket</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android-加密算法/">Android -加密算法</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android-常用功能/">Android -常用功能</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android-框架/">Android -框架</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android-源码解析/">Android -源码解析</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android-自定义view/">Android -自定义view</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Android-设计模式/">Android -设计模式</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/JAVA-并发/">JAVA -并发</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Java-SpringBoot/">Java -SpringBoot</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/Tomcat/">Tomcat</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/kotlin/">kotlin</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/数据库-JDBC/">数据库 -JDBC</a></li><li class="category-list-item"><a class="category-list-link" href="/categories/数据库-MySQL/">数据库 -MySQL</a></li></ul>
    </div>
  </div>


  
    

  
    
  
    
  <div class="widget-box">
    <h3 class="widget-title">归档</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/07/">July 2021</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/11/">November 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/10/">October 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/09/">September 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/08/">August 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/07/">July 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2019/06/">June 2019</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/10/">October 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/05/">May 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/03/">March 2018</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2018/02/">February 2018</a></li></ul>
    </div>
  </div>

  
    
  <div class="widget-box">
    <h3 class="widget-title">最新文章</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/2021/07/27/JAVA—公平锁，非公平锁，悲观锁，乐观锁，死锁/">JAVA—公平锁，非公平锁，悲观锁，乐观锁，死锁</a>
          </li>
        
          <li>
            <a href="/2021/07/19/JAVA—线程同步器AQS/">JAVA—线程同步器AQS</a>
          </li>
        
          <li>
            <a href="/2021/07/07/Android模拟点击/">Android模拟点击</a>
          </li>
        
          <li>
            <a href="/2019/11/27/SpringBoot系列-消息-RabbitMQ-（二十）/">SpringBoot系列-消息(RabbitMQ)（二十）</a>
          </li>
        
          <li>
            <a href="/2019/11/13/SpringBoot系列-Docker（十九）/">SpringBoot系列-Docker（十九）</a>
          </li>
        
      </ul>
    </div>
  </div>

  
      <div class="widget-box">
    <h3 class="widget-title">友情链接</h3>
    <div class="widget">
      
        <a class="hrf" style="display: block;" href="https://github.com/haichenyi" title target='_blank'
        >Github</a>
      
        <a class="hrf" style="display: block;" href="https://www.jianshu.com/u/6077ee440c37" title target='_blank'
        >简书</a>
      
        <a class="hrf" style="display: block;" href="https://blog.csdn.net/qq_27634797" title target='_blank'
        >CSDN</a>
      
    </div>
  </div>

  
</aside>
      </div>
      <footer id="footer">
  <div class="foot-box footers global-width">
    &copy;2017-2021 海晨忆 &nbsp;&nbsp;
    <script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span id="busuanzi_container_site_pv">阁下是第<span id="busuanzi_value_site_pv"></span>个访客</span>
  </div>
</footer>
      <script src="https://code.jquery.com/jquery-2.0.3.min.js"></script>
<script>
if (!window.jQuery) {
var script = document.createElement('script');
script.src = "/js/jquery-2.0.3.min.js";
document.body.write(script);
}
</script>

  <link rel="stylesheet" href="/fancybox/jquery.fancybox.css">
  <script src="/fancybox/jquery.fancybox.pack.js"></script>


<script src="/js/script.js"></script>



    </div>
    <nav id="mobile-nav" class="mobile-nav-box">
  <div class="mobile-nav-img mobile-nav-top"></div>
  
    <a href="/" class="mobile-nav-link">首页</a>
  
    <a href="/archives" class="mobile-nav-link">归档</a>
  
    <a href="/about" class="mobile-nav-link">简历</a>
  
  <div class="mobile-nav-img  mobile-nav-bottom"></div>
</nav>    
  </div>
</body>
</html>